package io.itit.ecp.admin.server.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import icu.mhb.mybatisplus.plugln.base.service.impl.JoinServiceImpl;
import icu.mhb.mybatisplus.plugln.extend.Joins;
import io.itit.ecp.admin.common.enums.IEarlyWarningEnums;
import io.itit.ecp.admin.common.enums.IMeterDeviceEnums;
import io.itit.ecp.admin.server.entity.*;
import io.itit.ecp.admin.server.entity.extend.EnergyDataExtEntity;
import io.itit.ecp.admin.server.mapper.EarlyWarningRecordMapper;
import io.itit.ecp.admin.server.service.*;
import io.itit.grass.common.exception.GrassException;
import io.itit.grass.common.server.dto.ParamDto;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * @Author：Roy
 * @Description：预警管理服务实现类
 * @Date：Create by 2023-12-15 11:20:26
 */
@Service
public class EarlyWarningRecordServiceImpl extends JoinServiceImpl<EarlyWarningRecordMapper, EarlyWarningRecordEntity> implements IEarlyWarningRecordService {

    @Resource
    private IEarlyWarningService earlyWarningService;

    @Resource
    private IEarlyWarningThresholdService earlyWarningThresholdService;

    @Resource
    private IEarlyWarningRecordService earlyWarningRecordService;

    @Resource
    private IEarlyWarningUserService earlyWarningUserService;

    @Resource
    private IEarlyWarningPushService earlyWarningPushService;

    @Override
    public Integer countRecords(String earlyWarningId, String date) {
        GrassException.nullThrowEx(earlyWarningId, "预警设置id不能为空");
        if (date == null) {
            date = DateUtil.today();
        }
        ParamDto dto = new ParamDto().add("earlyWarningId", earlyWarningId).add("date", date);
        return this.baseMapper.countRecords(dto);
    }

    @Override
    public void triggerWarning(String meterDeviceId, Date solidifyDateStart, Date solidifyDateEnd) {
        if (StringUtils.isEmpty(meterDeviceId)) {
            log.warn("triggerWarning meterDeviceId is null");
            return;
        }
        List<EarlyWarningEntity> warningEntities = earlyWarningService.lambdaQuery()
                .eq(EarlyWarningEntity::getMeterDeviceId, meterDeviceId)
//                .eq(EarlyWarningEntity::getWarningType, IEarlyWarningEnums.WarningType.warningType2.warningType)
                .ge(EarlyWarningEntity::getStartTime, solidifyDateStart)
                .gt(EarlyWarningEntity::getStartTime, solidifyDateEnd)
                .list();
        for (EarlyWarningEntity warningEntity : warningEntities) {
            String pushType = warningEntity.getPushType();
            if (StringUtils.isNotEmpty(pushType)) {
                        internalTriggerWarning(warningEntity, solidifyDateStart, solidifyDateEnd);
//                switch (pushType) {
//                    case "1":
//                        break;
//                    case "2":
//                        if (triggerCount(warningEntity) == 0) {
//                            internalTriggerWarning(warningEntity, solidifyDateStart, solidifyDateEnd);
//                        }
//                        break;
//                    case "3":
//                        if (triggerCount(warningEntity) <= 1) {
//                            internalTriggerWarning(warningEntity, solidifyDateStart, solidifyDateEnd);
//                        }
//                        break;
//                    case "4":
//                        if (triggerCount(warningEntity) <= 2) {
//                            internalTriggerWarning(warningEntity, solidifyDateStart, solidifyDateEnd);
//                        }
//                        break;
//                }
            }
        }
    }

    private void internalTriggerWarning(EarlyWarningEntity warningEntity, Date solidifyDateStart, Date solidifyDateEnd) {
        String meterCondition = warningEntity.getMeterCondition();
        if (StringUtils.isNotEmpty(meterCondition)) {
            String dateFormat = null;
            Date start = solidifyDateStart;
            Date end = solidifyDateEnd;
            switch (meterCondition) {
                case "1": // 按时计量
                    dateFormat = "yyyy-MM-dd HH:00"; //默认按时
                    start = DateUtil.ceiling(start, DateField.HOUR_OF_DAY);
                    end = DateUtil.ceiling(solidifyDateEnd, DateField.HOUR_OF_DAY);
                    break;
                case "2": // 按日计量
                    dateFormat = "yyyy-MM-dd";
                    start = DateUtil.beginOfDay(start);
                    end = DateUtil.endOfDay(end);
                    break;
                case "3": // 按月计量
                    dateFormat = "yyyy-MM";
                    start = DateUtil.beginOfMonth(start);
                    end = DateUtil.endOfMinute(end);
                    break;
            }
            if (StringUtils.isNotEmpty(dateFormat)) {
                String finalDateFormat = dateFormat;
                Map<String, List<EnergyDataEntity>> energyDataSolidifyDateMap;
                if (StringUtils.equals(warningEntity.getWarningType(), IEarlyWarningEnums.WarningType.warningType2.warningType)) {
                    energyDataSolidifyDateMap = Joins.of(EnergyDataEntity.class)
                            .select(EnergyDataEntity::getSolidifyDate, EnergyDataEntity::getMeterValue,
                                    EnergyDataEntity::getProductTypeId, EnergyDataEntity::getEnergyTypeUnit)
                            .leftJoin(MeterDeviceEntity.class, MeterDeviceEntity::getId, EnergyDataEntity::getMeterDeviceId)
                            .selectAs(t -> t.addFunAlias(MeterDeviceEntity::getDeviceCode, EnergyDataExtEntity::getDeviceCode)
                                    .addFunAlias(MeterDeviceEntity::getDeviceName, EnergyDataExtEntity::getDeviceName)
                                    .addFunAlias(MeterDeviceEntity::getReadMeterType, EnergyDataExtEntity::getReadMeterType)
                                    .addFunAlias(MeterDeviceEntity::getReadMeterTag, EnergyDataExtEntity::getReadMeterTag))
                            .notIn(MeterDeviceEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.getZeroCarbonList())
                            .end()
                            .eq(EnergyDataEntity::getMeterDeviceId, warningEntity.getMeterDeviceId())
                            .ge(EnergyDataEntity::getSolidifyDate, start)
                            .le(EnergyDataEntity::getSolidifyDate, end)
                            .joinList(EnergyDataEntity.class)
                            .stream()
                            .collect(Collectors.groupingBy(item -> DateUtil.format(item.getSolidifyDate(), finalDateFormat), TreeMap::new, Collectors.toList()));
                } else {
                    energyDataSolidifyDateMap = Joins.of(EnergyDataEntity.class)
                            .select(EnergyDataEntity::getSolidifyDate, EnergyDataEntity::getMeterValue,
                                    EnergyDataEntity::getProductTypeId, EnergyDataEntity::getEnergyTypeUnit)
                            .eq(EnergyDataEntity::getMeterDeviceId, warningEntity.getMeterDeviceId())
                            .ge(EnergyDataEntity::getSolidifyDate, start)
                            .le(EnergyDataEntity::getSolidifyDate, end)
                            .joinList(EnergyDataEntity.class)
                            .stream()
                            .collect(Collectors.groupingBy(item -> DateUtil.format(item.getSolidifyDate(), finalDateFormat), TreeMap::new, Collectors.toList()));
                }

                List<EarlyWarningThresholdEntity> recordList = earlyWarningThresholdService.lambdaQuery()
                        .eq(EarlyWarningThresholdEntity::getEarlyWarningId, warningEntity.getId())
                        .list();

                List<EarlyWarningUserEntity> userEntities = earlyWarningUserService.findByEarlyWarningId(warningEntity.getId());
                for (EarlyWarningThresholdEntity thresholdEntity : recordList) {
                    String judgeRule = thresholdEntity.getJudgeRule();
                    BigDecimal thresholdValue = thresholdEntity.getThresholdValue();
                    for (Map.Entry<String, List<EnergyDataEntity>> entry : energyDataSolidifyDateMap.entrySet()) {
                        BigDecimal value = entry.getValue().stream().map(EnergyDataEntity::getMeterValue)
                                .filter(Objects::nonNull)
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                        String energyType = entry.getValue().get(0).getEnergyTypeId();
                        String energyTypeUnit = entry.getValue().get(0).getEnergyTypeUnit();
                        if (("1".equals(judgeRule) && value.compareTo(thresholdValue) >= 0) ||
                                ("2".equals(judgeRule) && value.compareTo(thresholdValue) <= 0)) {
                            // 触发预警
                            EarlyWarningRecordEntity warningRecordEntity = new EarlyWarningRecordEntity();
                            warningRecordEntity.setEarlyWarningId(warningEntity.getId());
                            warningRecordEntity.setWarningName(warningEntity.getWarningName());
                            warningRecordEntity.setWarningType(warningEntity.getWarningType());
                            warningRecordEntity.setSceneProjectId(warningEntity.getSceneProjectId());
                            warningRecordEntity.setSceneEdificeId(warningEntity.getSceneEdificeId());
                            warningRecordEntity.setSceneFloorId(warningEntity.getSceneFloorId());
                            warningRecordEntity.setSceneRoomId(warningEntity.getSceneRoomId());
                            warningRecordEntity.setMeterDeviceId(warningEntity.getMeterDeviceId());
                            warningRecordEntity.setEnergyTypeId(energyType);
                            warningRecordEntity.setThresholdUnit(energyTypeUnit);
                            warningRecordEntity.setMeterCondition(meterCondition);
                            warningRecordEntity.setPushRule(warningEntity.getPushType());
                            warningRecordEntity.setJudgeRule(thresholdEntity.getJudgeRule());
                            warningRecordEntity.setThresholdLevel(thresholdEntity.getThresholdLevel());
                            warningRecordEntity.setMeterValue(value);
                            warningRecordEntity.setThresholdLevel(thresholdEntity.getThresholdLevel());
                            warningRecordEntity.setStatus("1");
                            earlyWarningRecordService.save(warningRecordEntity);
                            List<EarlyWarningPushEntity> pushEntities = userEntities.stream().map(item -> {
                                EarlyWarningPushEntity earlyWarningPushEntity = new EarlyWarningPushEntity();
                                earlyWarningPushEntity.setEarlyWarningId(warningEntity.getId());
                                earlyWarningPushEntity.setEarlyWarningRecordId(warningRecordEntity.getId());
                                earlyWarningPushEntity.setUserId(item.getUserId());
                                earlyWarningPushEntity.setStatus("1");
                                return earlyWarningPushEntity;
                            }).collect(Collectors.toList());
                            earlyWarningPushService.saveBatch(pushEntities);
                        }
                    }
                }
            }
        }
    }

    /**
     * 检查触发的次数
     */
    private int triggerCount(EarlyWarningEntity warningEntity) {
        return (int) earlyWarningRecordService.count(new LambdaQueryWrapper<EarlyWarningRecordEntity>()
                .eq(EarlyWarningRecordEntity::getEarlyWarningId, warningEntity.getId()));
    }
}
